{"cells":[{"cell_type":"code","execution_count":null,"id":"0ac1bf16","metadata":{"id":"0ac1bf16","colab":{"base_uri":"https://localhost:8080/"},"collapsed":true,"executionInfo":{"status":"ok","timestamp":1717420524965,"user_tz":-480,"elapsed":51322,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"0592372f-b53f-492b-a4d1-02d83a3b44f0"},"outputs":[{"output_type":"stream","name":"stdout","text":["Collecting langchain\n","  Downloading langchain-0.2.1-py3-none-any.whl (973 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m973.5/973.5 kB\u001b[0m \u001b[31m7.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hCollecting langchain_community\n","  Downloading langchain_community-0.2.1-py3-none-any.whl (2.1 MB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.1/2.1 MB\u001b[0m \u001b[31m45.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hCollecting langchain-openai\n","  Downloading langchain_openai-0.1.8-py3-none-any.whl (38 kB)\n","Collecting langchain_chroma\n","  Downloading langchain_chroma-0.1.1-py3-none-any.whl (8.5 kB)\n","Collecting langchainhub\n","  Downloading langchainhub-0.1.17-py3-none-any.whl (4.8 kB)\n","Requirement already satisfied: PyYAML>=5.3 in /usr/local/lib/python3.10/dist-packages (from langchain) (6.0.1)\n","Requirement already satisfied: SQLAlchemy<3,>=1.4 in /usr/local/lib/python3.10/dist-packages (from langchain) (2.0.30)\n","Requirement already satisfied: aiohttp<4.0.0,>=3.8.3 in /usr/local/lib/python3.10/dist-packages (from langchain) (3.9.5)\n","Requirement already satisfied: async-timeout<5.0.0,>=4.0.0 in /usr/local/lib/python3.10/dist-packages (from langchain) (4.0.3)\n","Collecting langchain-core<0.3.0,>=0.2.0 (from langchain)\n","  Downloading langchain_core-0.2.3-py3-none-any.whl (310 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m310.2/310.2 kB\u001b[0m \u001b[31m19.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hCollecting langchain-text-splitters<0.3.0,>=0.2.0 (from langchain)\n","  Downloading langchain_text_splitters-0.2.0-py3-none-any.whl (23 kB)\n","Collecting langsmith<0.2.0,>=0.1.17 (from langchain)\n","  Downloading langsmith-0.1.67-py3-none-any.whl (124 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m124.4/124.4 kB\u001b[0m \u001b[31m6.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hRequirement already satisfied: numpy<2,>=1 in /usr/local/lib/python3.10/dist-packages (from langchain) (1.25.2)\n","Requirement already satisfied: pydantic<3,>=1 in /usr/local/lib/python3.10/dist-packages (from langchain) (2.7.1)\n","Requirement already satisfied: requests<3,>=2 in /usr/local/lib/python3.10/dist-packages (from langchain) (2.31.0)\n","Requirement already satisfied: tenacity<9.0.0,>=8.1.0 in /usr/local/lib/python3.10/dist-packages (from langchain) (8.3.0)\n","Collecting dataclasses-json<0.7,>=0.5.7 (from langchain_community)\n","  Downloading dataclasses_json-0.6.6-py3-none-any.whl (28 kB)\n","Collecting openai<2.0.0,>=1.26.0 (from langchain-openai)\n","  Downloading openai-1.30.5-py3-none-any.whl (320 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m320.7/320.7 kB\u001b[0m \u001b[31m18.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hCollecting tiktoken<1,>=0.7 (from langchain-openai)\n","  Downloading tiktoken-0.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.1 MB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.1/1.1 MB\u001b[0m \u001b[31m37.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hCollecting chromadb<0.6.0,>=0.4.0 (from langchain_chroma)\n","  Downloading chromadb-0.5.0-py3-none-any.whl (526 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m526.8/526.8 kB\u001b[0m \u001b[31m24.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hCollecting fastapi<1,>=0.95.2 (from langchain_chroma)\n","  Downloading fastapi-0.111.0-py3-none-any.whl (91 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m92.0/92.0 kB\u001b[0m \u001b[31m5.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hCollecting types-requests<3.0.0.0,>=2.31.0.2 (from langchainhub)\n","  Downloading types_requests-2.32.0.20240602-py3-none-any.whl (15 kB)\n","Requirement already satisfied: aiosignal>=1.1.2 in /usr/local/lib/python3.10/dist-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (1.3.1)\n","Requirement already satisfied: attrs>=17.3.0 in /usr/local/lib/python3.10/dist-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (23.2.0)\n","Requirement already satisfied: frozenlist>=1.1.1 in /usr/local/lib/python3.10/dist-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (1.4.1)\n","Requirement already satisfied: multidict<7.0,>=4.5 in /usr/local/lib/python3.10/dist-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (6.0.5)\n","Requirement already satisfied: yarl<2.0,>=1.0 in /usr/local/lib/python3.10/dist-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (1.9.4)\n","Requirement already satisfied: build>=1.0.3 in /usr/local/lib/python3.10/dist-packages (from chromadb<0.6.0,>=0.4.0->langchain_chroma) (1.2.1)\n","Collecting chroma-hnswlib==0.7.3 (from chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading chroma_hnswlib-0.7.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.4 MB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.4/2.4 MB\u001b[0m \u001b[31m26.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hCollecting uvicorn[standard]>=0.18.3 (from chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading uvicorn-0.30.1-py3-none-any.whl (62 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m62.4/62.4 kB\u001b[0m \u001b[31m3.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hCollecting posthog>=2.4.0 (from chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading posthog-3.5.0-py2.py3-none-any.whl (41 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m41.3/41.3 kB\u001b[0m \u001b[31m2.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hRequirement already satisfied: typing-extensions>=4.5.0 in /usr/local/lib/python3.10/dist-packages (from chromadb<0.6.0,>=0.4.0->langchain_chroma) (4.11.0)\n","Collecting onnxruntime>=1.14.1 (from chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading onnxruntime-1.18.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (6.8 MB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m6.8/6.8 MB\u001b[0m \u001b[31m17.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hCollecting opentelemetry-api>=1.2.0 (from chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading opentelemetry_api-1.25.0-py3-none-any.whl (59 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m59.9/59.9 kB\u001b[0m \u001b[31m3.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hCollecting opentelemetry-exporter-otlp-proto-grpc>=1.2.0 (from chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading opentelemetry_exporter_otlp_proto_grpc-1.25.0-py3-none-any.whl (18 kB)\n","Collecting opentelemetry-instrumentation-fastapi>=0.41b0 (from chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading opentelemetry_instrumentation_fastapi-0.46b0-py3-none-any.whl (11 kB)\n","Collecting opentelemetry-sdk>=1.2.0 (from chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading opentelemetry_sdk-1.25.0-py3-none-any.whl (107 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m107.0/107.0 kB\u001b[0m \u001b[31m6.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hRequirement already satisfied: tokenizers>=0.13.2 in /usr/local/lib/python3.10/dist-packages (from chromadb<0.6.0,>=0.4.0->langchain_chroma) (0.19.1)\n","Collecting pypika>=0.48.9 (from chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading PyPika-0.48.9.tar.gz (67 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m67.3/67.3 kB\u001b[0m \u001b[31m4.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25h  Installing build dependencies ... \u001b[?25l\u001b[?25hdone\n","  Getting requirements to build wheel ... \u001b[?25l\u001b[?25hdone\n","  Preparing metadata (pyproject.toml) ... \u001b[?25l\u001b[?25hdone\n","Requirement already satisfied: tqdm>=4.65.0 in /usr/local/lib/python3.10/dist-packages (from chromadb<0.6.0,>=0.4.0->langchain_chroma) (4.66.4)\n","Collecting overrides>=7.3.1 (from chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading overrides-7.7.0-py3-none-any.whl (17 kB)\n","Requirement already satisfied: importlib-resources in /usr/local/lib/python3.10/dist-packages (from chromadb<0.6.0,>=0.4.0->langchain_chroma) (6.4.0)\n","Requirement already satisfied: grpcio>=1.58.0 in /usr/local/lib/python3.10/dist-packages (from chromadb<0.6.0,>=0.4.0->langchain_chroma) (1.64.0)\n","Collecting bcrypt>=4.0.1 (from chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading bcrypt-4.1.3-cp39-abi3-manylinux_2_28_x86_64.whl (283 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m283.7/283.7 kB\u001b[0m \u001b[31m29.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hRequirement already satisfied: typer>=0.9.0 in /usr/local/lib/python3.10/dist-packages (from chromadb<0.6.0,>=0.4.0->langchain_chroma) (0.9.4)\n","Collecting kubernetes>=28.1.0 (from chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading kubernetes-29.0.0-py2.py3-none-any.whl (1.6 MB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.6/1.6 MB\u001b[0m \u001b[31m54.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hCollecting mmh3>=4.0.1 (from chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading mmh3-4.1.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (67 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m67.6/67.6 kB\u001b[0m \u001b[31m8.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hCollecting orjson>=3.9.12 (from chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading orjson-3.10.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (142 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m142.5/142.5 kB\u001b[0m \u001b[31m14.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hCollecting marshmallow<4.0.0,>=3.18.0 (from dataclasses-json<0.7,>=0.5.7->langchain_community)\n","  Downloading marshmallow-3.21.2-py3-none-any.whl (49 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m49.3/49.3 kB\u001b[0m \u001b[31m5.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hCollecting typing-inspect<1,>=0.4.0 (from dataclasses-json<0.7,>=0.5.7->langchain_community)\n","  Downloading typing_inspect-0.9.0-py3-none-any.whl (8.8 kB)\n","Collecting starlette<0.38.0,>=0.37.2 (from fastapi<1,>=0.95.2->langchain_chroma)\n","  Downloading starlette-0.37.2-py3-none-any.whl (71 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m71.9/71.9 kB\u001b[0m \u001b[31m7.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hCollecting fastapi-cli>=0.0.2 (from fastapi<1,>=0.95.2->langchain_chroma)\n","  Downloading fastapi_cli-0.0.4-py3-none-any.whl (9.5 kB)\n","Collecting httpx>=0.23.0 (from fastapi<1,>=0.95.2->langchain_chroma)\n","  Downloading httpx-0.27.0-py3-none-any.whl (75 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m75.6/75.6 kB\u001b[0m \u001b[31m3.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hRequirement already satisfied: jinja2>=2.11.2 in /usr/local/lib/python3.10/dist-packages (from fastapi<1,>=0.95.2->langchain_chroma) (3.1.4)\n","Collecting python-multipart>=0.0.7 (from fastapi<1,>=0.95.2->langchain_chroma)\n","  Downloading python_multipart-0.0.9-py3-none-any.whl (22 kB)\n","Collecting ujson!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,>=4.0.1 (from fastapi<1,>=0.95.2->langchain_chroma)\n","  Downloading ujson-5.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (53 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m53.6/53.6 kB\u001b[0m \u001b[31m7.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hCollecting email_validator>=2.0.0 (from fastapi<1,>=0.95.2->langchain_chroma)\n","  Downloading email_validator-2.1.1-py3-none-any.whl (30 kB)\n","Collecting jsonpatch<2.0,>=1.33 (from langchain-core<0.3.0,>=0.2.0->langchain)\n","  Downloading jsonpatch-1.33-py2.py3-none-any.whl (12 kB)\n","Collecting packaging<24.0,>=23.2 (from langchain-core<0.3.0,>=0.2.0->langchain)\n","  Downloading packaging-23.2-py3-none-any.whl (53 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m53.0/53.0 kB\u001b[0m \u001b[31m6.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hRequirement already satisfied: anyio<5,>=3.5.0 in /usr/local/lib/python3.10/dist-packages (from openai<2.0.0,>=1.26.0->langchain-openai) (3.7.1)\n","Requirement already satisfied: distro<2,>=1.7.0 in /usr/lib/python3/dist-packages (from openai<2.0.0,>=1.26.0->langchain-openai) (1.7.0)\n","Requirement already satisfied: sniffio in /usr/local/lib/python3.10/dist-packages (from openai<2.0.0,>=1.26.0->langchain-openai) (1.3.1)\n","Requirement already satisfied: annotated-types>=0.4.0 in /usr/local/lib/python3.10/dist-packages (from pydantic<3,>=1->langchain) (0.7.0)\n","Requirement already satisfied: pydantic-core==2.18.2 in /usr/local/lib/python3.10/dist-packages (from pydantic<3,>=1->langchain) (2.18.2)\n","Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2->langchain) (3.3.2)\n","Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2->langchain) (3.7)\n","Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2->langchain) (2.0.7)\n","Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2->langchain) (2024.2.2)\n","Requirement already satisfied: greenlet!=0.4.17 in /usr/local/lib/python3.10/dist-packages (from SQLAlchemy<3,>=1.4->langchain) (3.0.3)\n","Requirement already satisfied: regex>=2022.1.18 in /usr/local/lib/python3.10/dist-packages (from tiktoken<1,>=0.7->langchain-openai) (2024.5.15)\n","Requirement already satisfied: exceptiongroup in /usr/local/lib/python3.10/dist-packages (from anyio<5,>=3.5.0->openai<2.0.0,>=1.26.0->langchain-openai) (1.2.1)\n","Requirement already satisfied: pyproject_hooks in /usr/local/lib/python3.10/dist-packages (from build>=1.0.3->chromadb<0.6.0,>=0.4.0->langchain_chroma) (1.1.0)\n","Requirement already satisfied: tomli>=1.1.0 in /usr/local/lib/python3.10/dist-packages (from build>=1.0.3->chromadb<0.6.0,>=0.4.0->langchain_chroma) (2.0.1)\n","Collecting dnspython>=2.0.0 (from email_validator>=2.0.0->fastapi<1,>=0.95.2->langchain_chroma)\n","  Downloading dnspython-2.6.1-py3-none-any.whl (307 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m307.7/307.7 kB\u001b[0m \u001b[31m32.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hCollecting typer>=0.9.0 (from chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading typer-0.12.3-py3-none-any.whl (47 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m47.2/47.2 kB\u001b[0m \u001b[31m5.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hCollecting httpcore==1.* (from httpx>=0.23.0->fastapi<1,>=0.95.2->langchain_chroma)\n","  Downloading httpcore-1.0.5-py3-none-any.whl (77 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m77.9/77.9 kB\u001b[0m \u001b[31m9.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hCollecting h11<0.15,>=0.13 (from httpcore==1.*->httpx>=0.23.0->fastapi<1,>=0.95.2->langchain_chroma)\n","  Downloading h11-0.14.0-py3-none-any.whl (58 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m58.3/58.3 kB\u001b[0m \u001b[31m7.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hRequirement already satisfied: MarkupSafe>=2.0 in /usr/local/lib/python3.10/dist-packages (from jinja2>=2.11.2->fastapi<1,>=0.95.2->langchain_chroma) (2.1.5)\n","Collecting jsonpointer>=1.9 (from jsonpatch<2.0,>=1.33->langchain-core<0.3.0,>=0.2.0->langchain)\n","  Downloading jsonpointer-2.4-py2.py3-none-any.whl (7.8 kB)\n","Requirement already satisfied: six>=1.9.0 in /usr/local/lib/python3.10/dist-packages (from kubernetes>=28.1.0->chromadb<0.6.0,>=0.4.0->langchain_chroma) (1.16.0)\n","Requirement already satisfied: python-dateutil>=2.5.3 in /usr/local/lib/python3.10/dist-packages (from kubernetes>=28.1.0->chromadb<0.6.0,>=0.4.0->langchain_chroma) (2.8.2)\n","Requirement already satisfied: google-auth>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from kubernetes>=28.1.0->chromadb<0.6.0,>=0.4.0->langchain_chroma) (2.27.0)\n","Requirement already satisfied: websocket-client!=0.40.0,!=0.41.*,!=0.42.*,>=0.32.0 in /usr/local/lib/python3.10/dist-packages (from kubernetes>=28.1.0->chromadb<0.6.0,>=0.4.0->langchain_chroma) (1.8.0)\n","Requirement already satisfied: requests-oauthlib in /usr/local/lib/python3.10/dist-packages (from kubernetes>=28.1.0->chromadb<0.6.0,>=0.4.0->langchain_chroma) (1.3.1)\n","Requirement already satisfied: oauthlib>=3.2.2 in /usr/local/lib/python3.10/dist-packages (from kubernetes>=28.1.0->chromadb<0.6.0,>=0.4.0->langchain_chroma) (3.2.2)\n","Collecting coloredlogs (from onnxruntime>=1.14.1->chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading coloredlogs-15.0.1-py2.py3-none-any.whl (46 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m46.0/46.0 kB\u001b[0m \u001b[31m5.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hRequirement already satisfied: flatbuffers in /usr/local/lib/python3.10/dist-packages (from onnxruntime>=1.14.1->chromadb<0.6.0,>=0.4.0->langchain_chroma) (24.3.25)\n","Requirement already satisfied: protobuf in /usr/local/lib/python3.10/dist-packages (from onnxruntime>=1.14.1->chromadb<0.6.0,>=0.4.0->langchain_chroma) (3.20.3)\n","Requirement already satisfied: sympy in /usr/local/lib/python3.10/dist-packages (from onnxruntime>=1.14.1->chromadb<0.6.0,>=0.4.0->langchain_chroma) (1.12)\n","Collecting deprecated>=1.2.6 (from opentelemetry-api>=1.2.0->chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading Deprecated-1.2.14-py2.py3-none-any.whl (9.6 kB)\n","Requirement already satisfied: importlib-metadata<=7.1,>=6.0 in /usr/local/lib/python3.10/dist-packages (from opentelemetry-api>=1.2.0->chromadb<0.6.0,>=0.4.0->langchain_chroma) (7.1.0)\n","Requirement already satisfied: googleapis-common-protos~=1.52 in /usr/local/lib/python3.10/dist-packages (from opentelemetry-exporter-otlp-proto-grpc>=1.2.0->chromadb<0.6.0,>=0.4.0->langchain_chroma) (1.63.0)\n","Collecting opentelemetry-exporter-otlp-proto-common==1.25.0 (from opentelemetry-exporter-otlp-proto-grpc>=1.2.0->chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading opentelemetry_exporter_otlp_proto_common-1.25.0-py3-none-any.whl (17 kB)\n","Collecting opentelemetry-proto==1.25.0 (from opentelemetry-exporter-otlp-proto-grpc>=1.2.0->chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading opentelemetry_proto-1.25.0-py3-none-any.whl (52 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m52.5/52.5 kB\u001b[0m \u001b[31m6.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hCollecting opentelemetry-instrumentation-asgi==0.46b0 (from opentelemetry-instrumentation-fastapi>=0.41b0->chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading opentelemetry_instrumentation_asgi-0.46b0-py3-none-any.whl (14 kB)\n","Collecting opentelemetry-instrumentation==0.46b0 (from opentelemetry-instrumentation-fastapi>=0.41b0->chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading opentelemetry_instrumentation-0.46b0-py3-none-any.whl (29 kB)\n","Collecting opentelemetry-semantic-conventions==0.46b0 (from opentelemetry-instrumentation-fastapi>=0.41b0->chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading opentelemetry_semantic_conventions-0.46b0-py3-none-any.whl (130 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m130.5/130.5 kB\u001b[0m \u001b[31m16.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hCollecting opentelemetry-util-http==0.46b0 (from opentelemetry-instrumentation-fastapi>=0.41b0->chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading opentelemetry_util_http-0.46b0-py3-none-any.whl (6.9 kB)\n","Requirement already satisfied: setuptools>=16.0 in /usr/local/lib/python3.10/dist-packages (from opentelemetry-instrumentation==0.46b0->opentelemetry-instrumentation-fastapi>=0.41b0->chromadb<0.6.0,>=0.4.0->langchain_chroma) (67.7.2)\n","Requirement already satisfied: wrapt<2.0.0,>=1.0.0 in /usr/local/lib/python3.10/dist-packages (from opentelemetry-instrumentation==0.46b0->opentelemetry-instrumentation-fastapi>=0.41b0->chromadb<0.6.0,>=0.4.0->langchain_chroma) (1.14.1)\n","Collecting asgiref~=3.0 (from opentelemetry-instrumentation-asgi==0.46b0->opentelemetry-instrumentation-fastapi>=0.41b0->chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading asgiref-3.8.1-py3-none-any.whl (23 kB)\n","Collecting monotonic>=1.5 (from posthog>=2.4.0->chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading monotonic-1.6-py2.py3-none-any.whl (8.2 kB)\n","Collecting backoff>=1.10.0 (from posthog>=2.4.0->chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading backoff-2.2.1-py3-none-any.whl (15 kB)\n","Requirement already satisfied: huggingface-hub<1.0,>=0.16.4 in /usr/local/lib/python3.10/dist-packages (from tokenizers>=0.13.2->chromadb<0.6.0,>=0.4.0->langchain_chroma) (0.23.1)\n","Requirement already satisfied: click>=8.0.0 in /usr/local/lib/python3.10/dist-packages (from typer>=0.9.0->chromadb<0.6.0,>=0.4.0->langchain_chroma) (8.1.7)\n","Collecting shellingham>=1.3.0 (from typer>=0.9.0->chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading shellingham-1.5.4-py2.py3-none-any.whl (9.8 kB)\n","Requirement already satisfied: rich>=10.11.0 in /usr/local/lib/python3.10/dist-packages (from typer>=0.9.0->chromadb<0.6.0,>=0.4.0->langchain_chroma) (13.7.1)\n","Collecting mypy-extensions>=0.3.0 (from typing-inspect<1,>=0.4.0->dataclasses-json<0.7,>=0.5.7->langchain_community)\n","  Downloading mypy_extensions-1.0.0-py3-none-any.whl (4.7 kB)\n","Collecting httptools>=0.5.0 (from uvicorn[standard]>=0.18.3->chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading httptools-0.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (341 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m341.4/341.4 kB\u001b[0m \u001b[31m36.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hCollecting python-dotenv>=0.13 (from uvicorn[standard]>=0.18.3->chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading python_dotenv-1.0.1-py3-none-any.whl (19 kB)\n","Collecting uvloop!=0.15.0,!=0.15.1,>=0.14.0 (from uvicorn[standard]>=0.18.3->chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading uvloop-0.19.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.4 MB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3.4/3.4 MB\u001b[0m \u001b[31m83.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hCollecting watchfiles>=0.13 (from uvicorn[standard]>=0.18.3->chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading watchfiles-0.22.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.2 MB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.2/1.2 MB\u001b[0m \u001b[31m68.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hCollecting websockets>=10.4 (from uvicorn[standard]>=0.18.3->chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading websockets-12.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (130 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m130.2/130.2 kB\u001b[0m \u001b[31m4.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hRequirement already satisfied: cachetools<6.0,>=2.0.0 in /usr/local/lib/python3.10/dist-packages (from google-auth>=1.0.1->kubernetes>=28.1.0->chromadb<0.6.0,>=0.4.0->langchain_chroma) (5.3.3)\n","Requirement already satisfied: pyasn1-modules>=0.2.1 in /usr/local/lib/python3.10/dist-packages (from google-auth>=1.0.1->kubernetes>=28.1.0->chromadb<0.6.0,>=0.4.0->langchain_chroma) (0.4.0)\n","Requirement already satisfied: rsa<5,>=3.1.4 in /usr/local/lib/python3.10/dist-packages (from google-auth>=1.0.1->kubernetes>=28.1.0->chromadb<0.6.0,>=0.4.0->langchain_chroma) (4.9)\n","Requirement already satisfied: filelock in /usr/local/lib/python3.10/dist-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers>=0.13.2->chromadb<0.6.0,>=0.4.0->langchain_chroma) (3.14.0)\n","Requirement already satisfied: fsspec>=2023.5.0 in /usr/local/lib/python3.10/dist-packages (from huggingface-hub<1.0,>=0.16.4->tokenizers>=0.13.2->chromadb<0.6.0,>=0.4.0->langchain_chroma) (2023.6.0)\n","Requirement already satisfied: zipp>=0.5 in /usr/local/lib/python3.10/dist-packages (from importlib-metadata<=7.1,>=6.0->opentelemetry-api>=1.2.0->chromadb<0.6.0,>=0.4.0->langchain_chroma) (3.18.2)\n","Requirement already satisfied: markdown-it-py>=2.2.0 in /usr/local/lib/python3.10/dist-packages (from rich>=10.11.0->typer>=0.9.0->chromadb<0.6.0,>=0.4.0->langchain_chroma) (3.0.0)\n","Requirement already satisfied: pygments<3.0.0,>=2.13.0 in /usr/local/lib/python3.10/dist-packages (from rich>=10.11.0->typer>=0.9.0->chromadb<0.6.0,>=0.4.0->langchain_chroma) (2.16.1)\n","Collecting humanfriendly>=9.1 (from coloredlogs->onnxruntime>=1.14.1->chromadb<0.6.0,>=0.4.0->langchain_chroma)\n","  Downloading humanfriendly-10.0-py2.py3-none-any.whl (86 kB)\n","\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m86.8/86.8 kB\u001b[0m \u001b[31m8.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n","\u001b[?25hRequirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.10/dist-packages (from sympy->onnxruntime>=1.14.1->chromadb<0.6.0,>=0.4.0->langchain_chroma) (1.3.0)\n","Requirement already satisfied: mdurl~=0.1 in /usr/local/lib/python3.10/dist-packages (from markdown-it-py>=2.2.0->rich>=10.11.0->typer>=0.9.0->chromadb<0.6.0,>=0.4.0->langchain_chroma) (0.1.2)\n","Requirement already satisfied: pyasn1<0.7.0,>=0.4.6 in /usr/local/lib/python3.10/dist-packages (from pyasn1-modules>=0.2.1->google-auth>=1.0.1->kubernetes>=28.1.0->chromadb<0.6.0,>=0.4.0->langchain_chroma) (0.6.0)\n","Building wheels for collected packages: pypika\n","  Building wheel for pypika (pyproject.toml) ... \u001b[?25l\u001b[?25hdone\n","  Created wheel for pypika: filename=PyPika-0.48.9-py2.py3-none-any.whl size=53724 sha256=e305edb4b7c850a10402dd4df599d82acbd5ed0ae39efc9dc0ea1a33acaf91e5\n","  Stored in directory: /root/.cache/pip/wheels/e1/26/51/d0bffb3d2fd82256676d7ad3003faea3bd6dddc9577af665f4\n","Successfully built pypika\n","Installing collected packages: pypika, monotonic, mmh3, websockets, uvloop, ujson, types-requests, shellingham, python-multipart, python-dotenv, packaging, overrides, orjson, opentelemetry-util-http, opentelemetry-proto, mypy-extensions, jsonpointer, humanfriendly, httptools, h11, dnspython, deprecated, chroma-hnswlib, bcrypt, backoff, asgiref, watchfiles, uvicorn, typing-inspect, tiktoken, starlette, posthog, opentelemetry-exporter-otlp-proto-common, opentelemetry-api, marshmallow, langchainhub, jsonpatch, httpcore, email_validator, coloredlogs, typer, opentelemetry-semantic-conventions, opentelemetry-instrumentation, onnxruntime, langsmith, kubernetes, httpx, dataclasses-json, opentelemetry-sdk, opentelemetry-instrumentation-asgi, openai, langchain-core, fastapi-cli, opentelemetry-instrumentation-fastapi, opentelemetry-exporter-otlp-proto-grpc, langchain-text-splitters, langchain-openai, fastapi, langchain, chromadb, langchain_community, langchain_chroma\n","  Attempting uninstall: packaging\n","    Found existing installation: packaging 24.0\n","    Uninstalling packaging-24.0:\n","      Successfully uninstalled packaging-24.0\n","  Attempting uninstall: typer\n","    Found existing installation: typer 0.9.4\n","    Uninstalling typer-0.9.4:\n","      Successfully uninstalled typer-0.9.4\n","\u001b[31mERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.\n","spacy 3.7.4 requires typer<0.10.0,>=0.3.0, but you have typer 0.12.3 which is incompatible.\n","weasel 0.3.4 requires typer<0.10.0,>=0.3.0, but you have typer 0.12.3 which is incompatible.\u001b[0m\u001b[31m\n","\u001b[0mSuccessfully installed asgiref-3.8.1 backoff-2.2.1 bcrypt-4.1.3 chroma-hnswlib-0.7.3 chromadb-0.5.0 coloredlogs-15.0.1 dataclasses-json-0.6.6 deprecated-1.2.14 dnspython-2.6.1 email_validator-2.1.1 fastapi-0.111.0 fastapi-cli-0.0.4 h11-0.14.0 httpcore-1.0.5 httptools-0.6.1 httpx-0.27.0 humanfriendly-10.0 jsonpatch-1.33 jsonpointer-2.4 kubernetes-29.0.0 langchain-0.2.1 langchain-core-0.2.3 langchain-openai-0.1.8 langchain-text-splitters-0.2.0 langchain_chroma-0.1.1 langchain_community-0.2.1 langchainhub-0.1.17 langsmith-0.1.67 marshmallow-3.21.2 mmh3-4.1.0 monotonic-1.6 mypy-extensions-1.0.0 onnxruntime-1.18.0 openai-1.30.5 opentelemetry-api-1.25.0 opentelemetry-exporter-otlp-proto-common-1.25.0 opentelemetry-exporter-otlp-proto-grpc-1.25.0 opentelemetry-instrumentation-0.46b0 opentelemetry-instrumentation-asgi-0.46b0 opentelemetry-instrumentation-fastapi-0.46b0 opentelemetry-proto-1.25.0 opentelemetry-sdk-1.25.0 opentelemetry-semantic-conventions-0.46b0 opentelemetry-util-http-0.46b0 orjson-3.10.3 overrides-7.7.0 packaging-23.2 posthog-3.5.0 pypika-0.48.9 python-dotenv-1.0.1 python-multipart-0.0.9 shellingham-1.5.4 starlette-0.37.2 tiktoken-0.7.0 typer-0.12.3 types-requests-2.32.0.20240602 typing-inspect-0.9.0 ujson-5.10.0 uvicorn-0.30.1 uvloop-0.19.0 watchfiles-0.22.0 websockets-12.0\n"]}],"source":["pip install langchain langchain_community langchain-openai langchain_chroma langchainhub"]},{"cell_type":"markdown","id":"064c13b6","metadata":{"id":"064c13b6"},"source":["### LangSmith\n","\n","使用LangChain构建的许多应用程序将都包含多个步骤和多次调用LLM调用。随着这些应用程序变得越来越复杂，能够检查chain或agent内部发生的细节变得至关重要。这样做的最佳方式是使用[LangSmith](https://smith.langchain.com/)。\n","\n","请注意，LangSmith并非必需，它只是在我们开发调试应用的时候非常有用。如果想使用可以在[官网](https://smith.langchain.com/)注册后申请秘钥，每个月都会有一定的免费使用额度，足够我们学习和测试，将key设置在的环境变量中就可以轻松使用LangSmith。\n","\n","notebook中设置"]},{"cell_type":"code","execution_count":null,"id":"63798aeb","metadata":{"id":"63798aeb"},"outputs":[],"source":["import os\n","from google.colab import userdata\n","os.environ[\"OPENAI_API_KEY\"] = userdata.get('OPENAI_API_KEY')\n","os.environ[\"OPENAI_API_BASE\"] = userdata.get('OPENAI_API_BASE')\n","os.environ[\"LANGCHAIN_TRACING_V2\"] = \"true\"\n","os.environ[\"LANGCHAIN_API_KEY\"] = userdata.get('LANGCHAIN_API_KEY')"]},{"cell_type":"markdown","id":"aef7bacd","metadata":{"id":"aef7bacd"},"source":["## Preview\n","\n","在本指南中，我们将基于网页上构建一个问答应用程序。\n","\n","我们可以创建一个简单的本地知识库索引和 RAG 链来实现这个功能，这大约只需要 20 行代码。\n","\n","- OpenAI"]},{"cell_type":"code","execution_count":null,"id":"3dd18136","metadata":{"id":"3dd18136"},"outputs":[],"source":["from langchain_openai import ChatOpenAI\n","llm = ChatOpenAI(model=\"gpt-3.5-turbo-0125\")"]},{"cell_type":"code","source":["llm.invoke(\"什么是Tree of Thoughts?\")"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"FZI_kE6WMLyF","executionInfo":{"status":"ok","timestamp":1717420695858,"user_tz":-480,"elapsed":5747,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"24120bc5-d52a-4923-b382-955c3a1a05a0"},"id":"FZI_kE6WMLyF","execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["AIMessage(content='Tree of Thoughts是一种概念，代表一个人的思维模式和思想体系。这个概念类似于一个树，树干代表一个人的核心信念和价值观，树枝代表不同的思维路径和分支，叶子代表具体的想法和观点。通过理解和研究一个人的Tree of Thoughts，可以更好地了解他们的思维方式和决策过程。这个概念也可以帮助人们更好地管理自己的思维，并促进思维的发展和成长。', response_metadata={'token_usage': {'completion_tokens': 171, 'prompt_tokens': 15, 'total_tokens': 186}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': 'fp_811936bd4f', 'finish_reason': 'stop', 'logprobs': None}, id='run-d2a1b112-10d3-4336-8002-7633dd610b75-0', usage_metadata={'input_tokens': 15, 'output_tokens': 171, 'total_tokens': 186})"]},"metadata":{},"execution_count":4}]},{"cell_type":"code","execution_count":null,"id":"34d16f7b","metadata":{"id":"34d16f7b"},"outputs":[],"source":["import bs4\n","from langchain_chroma import Chroma\n","from langchain_community.document_loaders import WebBaseLoader\n","from langchain_openai import OpenAIEmbeddings\n","from langchain_text_splitters import RecursiveCharacterTextSplitter\n","# Load, chunk and index the contents of the blog.\n","loader = WebBaseLoader(\n","    web_paths=(\"https://lilianweng.github.io/posts/2023-06-23-agent/\",),\n","    bs_kwargs=dict(\n","        parse_only=bs4.SoupStrainer(\n","            class_=(\"post-content\", \"post-title\", \"post-header\")\n",")\n","),\n",")\n","docs = loader.load()\n","text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)\n","splits = text_splitter.split_documents(docs)\n","vectorstore = Chroma.from_documents(documents=splits, embedding=OpenAIEmbeddings())\n","# Retrieve and generate using the relevant snippets of the blog.\n","retriever = vectorstore.as_retriever()\n"]},{"cell_type":"code","source":["from langchain import hub\n","from langchain_core.output_parsers import StrOutputParser\n","from langchain_core.runnables import RunnablePassthrough\n","prompt = hub.pull(\"rlm/rag-prompt\")\n","\n","def format_docs(docs):\n","  return \"\\n\\n\".join(doc.page_content for doc in docs)\n","\n","rag_chain = (\n","{\"context\": retriever | format_docs, \"question\": RunnablePassthrough()}\n","| prompt\n","| llm\n","| StrOutputParser()\n",")\n","rag_chain.invoke(\"什么是Tree of Thoughts?\")"],"metadata":{"colab":{"base_uri":"https://localhost:8080/","height":52},"id":"FfKj0PPTMWfO","executionInfo":{"status":"ok","timestamp":1717420921693,"user_tz":-480,"elapsed":10086,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"43a1fe5a-d948-4612-c36b-1ccb0e91a384"},"id":"FfKj0PPTMWfO","execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["'Tree of Thoughts 是一种扩展了CoT的技术，通过在每个步骤探索多种推理可能性来拆分问题，生成多个思考的树结构。搜索过程可以采用BFS或DFS，每个状态由分类器或多数投票评估。ReAct在知识密集型任务和决策任务上的实验中表现更好，其中Thought步骤被移除。Reflexion是一个框架，为智能体提供动态记忆和自我反思能力，以提高推理能力。'"],"application/vnd.google.colaboratory.intrinsic+json":{"type":"string"}},"metadata":{},"execution_count":9}]},{"cell_type":"markdown","id":"1c7cb6fa","metadata":{"id":"1c7cb6fa"},"source":["**API 调用:**[WebBaseLoader](https://api.python.langchain.com/en/latest/document_loaders/langchain_community.document_loaders.web_base.WebBaseLoader.html) | [StrOutputParser](https://api.python.langchain.com/en/latest/output_parsers/langchain_core.output_parsers.string.StrOutputParser.html) | [RunnablePassthrough](https://api.python.langchain.com/en/latest/runnables/langchain_core.runnables.passthrough.RunnablePassthrough.html) | [OpenAIEmbeddings](https://api.python.langchain.com/en/latest/embeddings/langchain_openai.embeddings.base.OpenAIEmbeddings.html) | [RecursiveCharacterTextSplitter](https://api.python.langchain.com/en/latest/character/langchain_text_splitters.character.RecursiveCharacterTextSplitter.html)"]},{"cell_type":"code","execution_count":null,"id":"5f8e44e7","metadata":{"id":"5f8e44e7"},"outputs":[],"source":["# cleanup\n","vectorstore.delete_collection()"]},{"cell_type":"markdown","id":"1e8c9819","metadata":{"id":"1e8c9819"},"source":["查看 [LangSmith trace](https://smith.langchain.com/public/1c6ca97e-445b-4d00-84b4-c7befcbc59fe/r).\n","\n","## 详细流程\n","\n","让我们逐步解释上面的代码，以便真正理解代码到底进行了什么操作。\n","\n","## 1. 创建索引: 加载数据\n","\n","加载数据我们可以使用文档加载器（[DocumentLoaders](https://python.langchain.com/v0.2/docs/concepts/#document-loaders)）来完成，它们是从源加载数据并返回[Documents](https://api.python.langchain.com/en/latest/documents/langchain_core.documents.base.Document.html)列表的对象。`Document` 是一个带有 `page_content` (str) 和 `metadata` (dict) 的对象。\n","\n","对于加载网页内容，我们将使用[WebBaseLoader](https://python.langchain.com/v0.2/docs/integrations/document_loaders/web_base/)（属于文档加载器的一种），它使用 `urllib` 从 web URL 加载 HTML，然后使用 `BeautifulSoup` 将其解析为文本。我们可以通过向 `bs_kwargs` 传递参数来自定义 HTML -> 文本解析（参见[BeautifulSoup文档](https://beautiful-soup-4.readthedocs.io/en/latest/#beautifulsoup)）。在这种情况下，只有具有“post-content”、“post-title”或“post-header”类的 HTML 标签是相关的，所以我们将删除所有其他标签。"]},{"cell_type":"code","execution_count":null,"id":"88253b57","metadata":{"id":"88253b57","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1717421079274,"user_tz":-480,"elapsed":495,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"b110334e-66a0-4224-c0e5-1de904f63ee7"},"outputs":[{"output_type":"execute_result","data":{"text/plain":["43131"]},"metadata":{},"execution_count":11}],"source":["import bs4\n","from langchain_community.document_loaders import WebBaseLoader\n","# Only keep post title, headers, and content from the full HTML.\n","bs4_strainer = bs4.SoupStrainer(class_=(\"post-title\", \"post-header\", \"post-content\"))\n","loader = WebBaseLoader(\n","    web_paths=(\"https://lilianweng.github.io/posts/2023-06-23-agent/\",),\n","    bs_kwargs={\"parse_only\": bs4_strainer},\n",")\n","docs = loader.load()\n","len(docs[0].page_content)\n"]},{"cell_type":"markdown","id":"591f9973","metadata":{"id":"591f9973"},"source":["**API 调用:**[WebBaseLoader](https://api.python.langchain.com/en/latest/document_loaders/langchain_community.document_loaders.web_base.WebBaseLoader.html)"]},{"cell_type":"code","execution_count":null,"id":"a5d9d87b","metadata":{"id":"a5d9d87b","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1717421097180,"user_tz":-480,"elapsed":498,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"eb717c1c-977a-47eb-d336-3958ead2ef70"},"outputs":[{"output_type":"stream","name":"stdout","text":["\n","\n","      LLM Powered Autonomous Agents\n","    \n","Date: June 23, 2023  |  Estimated Reading Time: 31 min  |  Author: Lilian Weng\n","\n","\n","Building agents with LLM (large language model) as its core controller is a cool concept. Several proof-of-concepts demos, such as AutoGPT, GPT-Engineer and BabyAGI, serve as inspiring examples. The potentiality of LLM extends beyond generating well-written copies, stories, essays and programs; it can be framed as a powerful general problem solver.\n","Agent System Overview#\n","In\n"]}],"source":["print(docs[0].page_content[:500])"]},{"cell_type":"markdown","id":"cd4e7cac","metadata":{"id":"cd4e7cac"},"source":["### `DocumentLoader`\n","\n","`DocumentLoader`: 将数据源加载成`Documents` 文本列表\n","\n","- [Docs](https://python.langchain.com/v0.2/docs/how_to/#document-loaders): 怎样使用文档加载器 `DocumentLoaders`.\n","- [Integrations](https://python.langchain.com/v0.2/docs/integrations/document_loaders/): 160+ 可供选择的文档类型集成。\n","- [Interface](https://api.python.langchain.com/en/latest/document_loaders/langchain_core.document_loaders.base.BaseLoader.html): API 的基本接口。\n","\n","## 2. 创建索引: 分割\n","\n","我们的加载文档超过42,000个字符。这太长了，很多模型的上下文窗口无法完全容纳。即使是那些可以完全容纳整篇文章的模型，也很难在非常长的输入中找到信息。\n","\n","为了处理这个问题，我们将把“文档”分成多个块进行嵌入和向量存储。这样可以帮助我们在运行时只检索出最相关的部分博客文章。\n","\n","在这种情况下，我们将把我们的文档分成每1000个字符一组，每组之间有200个字符的重叠。重叠有助于减少分离语句与与之相关的重要上下文的可能性。我们使用了[RecursiveCharacterTextSplitter](https://python.langchain.com/v0.2/docs/how_to/recursive_text_splitter/)，它将递归地使用常见的分隔符（例如换行符）拆分文档，直到每个块的大小合适。这是通用文本用例的推荐文本拆分器。\n","\n","我们设置 `add_start_index=True`，这样每个拆分的文档在初始文档中开始的字符索引位置将被保留为元数据 `start_index`属性。"]},{"cell_type":"code","execution_count":null,"id":"b059f82b","metadata":{"id":"b059f82b","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1717421316109,"user_tz":-480,"elapsed":665,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"bdccda78-b027-4e7c-adc1-7fddc5b919c9"},"outputs":[{"output_type":"execute_result","data":{"text/plain":["66"]},"metadata":{},"execution_count":13}],"source":["from langchain_text_splitters import RecursiveCharacterTextSplitter\n","text_splitter = RecursiveCharacterTextSplitter(\n","    chunk_size=1000, chunk_overlap=200, add_start_index=True\n",")\n","all_splits = text_splitter.split_documents(docs)\n","len(all_splits)"]},{"cell_type":"markdown","id":"4f6ff09d","metadata":{"id":"4f6ff09d"},"source":["**API Reference:**[RecursiveCharacterTextSplitter](https://api.python.langchain.com/en/latest/character/langchain_text_splitters.character.RecursiveCharacterTextSplitter.html)"]},{"cell_type":"code","execution_count":null,"id":"c37e5fce","metadata":{"id":"c37e5fce","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1717421328030,"user_tz":-480,"elapsed":524,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"548e1fba-1b34-4715-8047-e36cd799d568"},"outputs":[{"output_type":"execute_result","data":{"text/plain":["969"]},"metadata":{},"execution_count":14}],"source":["len(all_splits[0].page_content)"]},{"cell_type":"code","execution_count":null,"id":"0009f6b3","metadata":{"id":"0009f6b3","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1717421337014,"user_tz":-480,"elapsed":537,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"39d455c8-3e3c-4aee-a52c-3ea80f93ee1a"},"outputs":[{"output_type":"execute_result","data":{"text/plain":["{'source': 'https://lilianweng.github.io/posts/2023-06-23-agent/',\n"," 'start_index': 7056}"]},"metadata":{},"execution_count":15}],"source":["all_splits[10].metadata"]},{"cell_type":"markdown","id":"c0bd83f8","metadata":{"id":"c0bd83f8"},"source":["### `TextSplitter`\n","\n","`TextSplitter` （ `DocumentTransformer`的子类）: 将`Document`列表分割为更小的块的对象。\n","\n","- 探索[上下文感知分割器](https://python.langchain.com/v0.2/docs/how_to/#text-splitters)，它们保留原始文档中每个分割的位置（“context”）。\n","- [Code (py or js)](https://python.langchain.com/v0.2/docs/integrations/document_loaders/source_code/)\n","- [Scientific papers](https://python.langchain.com/v0.2/docs/integrations/document_loaders/grobid/)\n","- [Interface](https://api.python.langchain.com/en/latest/base/langchain_text_splitters.base.TextSplitter.html): API 的基本接口。\n","\n","`DocumentTransformer`: 执行对不同类型文档进行切割转换的对象。\n","\n","- [Docs](https://python.langchain.com/v0.2/docs/how_to/#text-splitters): 如何使用 `DocumentTransformers`\n","- [Integrations](https://python.langchain.com/v0.2/docs/integrations/document_transformers/)\n","- [Interface](https://api.python.langchain.com/en/latest/documents/langchain_core.documents.transformers.BaseDocumentTransformer.html): API 调用\n","\n","## 3. 创建索引: 存储\n","\n","现在我们需要为我们的 66 个文本块建立索引，以便我们可以在运行时对它们进行搜索。最常见的做法是嵌入每个文档分割的内容，并将这些嵌入插入到向量数据库（或向量存储）中。当我们想要在我们的分割上搜索时，我们获取一个文本搜索查询，并对其进行嵌入，然后执行某种“相似性”搜索，以识别与我们的查询嵌入最相似的存储分割。最简单的相似度度量是余弦相似度 — 我们测量每对嵌入之间的角的余弦（这些嵌入是高维向量）。\n","\n","我们可以使用[Chroma](https://python.langchain.com/v0.2/docs/integrations/vectorstores/chroma/)向量存储和[OpenAIEmbeddings](https://python.langchain.com/v0.2/docs/integrations/text_embedding/openai/)模型，在一个方法中完成嵌入和存储所有分割文档。"]},{"cell_type":"code","execution_count":null,"id":"edced8a4","metadata":{"id":"edced8a4"},"outputs":[],"source":["from langchain_chroma import Chroma\n","from langchain_openai import OpenAIEmbeddings\n","vectorstore = Chroma.from_documents(documents=all_splits, embedding=OpenAIEmbeddings())"]},{"cell_type":"markdown","id":"d1720ea8","metadata":{"id":"d1720ea8"},"source":["**API 调用:**[OpenAIEmbeddings](https://api.python.langchain.com/en/latest/embeddings/langchain_openai.embeddings.base.OpenAIEmbeddings.html)\n","\n","### Go deeper\n","\n","`Embeddings`: 文本向量嵌入模型的包装器，用于将文本转换为向量。\n","\n","- [Docs](https://python.langchain.com/v0.2/docs/how_to/embed_text/): 文本嵌入详情\n","- [Integrations](https://python.langchain.com/v0.2/docs/integrations/text_embedding/): langchain 的向量模型集成，实现了`Embeddings` 接口的对象\n","- [Interface](https://api.python.langchain.com/en/latest/embeddings/langchain_core.embeddings.Embeddings.html): API 调用\n","\n","`VectorStore`: 向量数据库的封装，用于存储和查询向量。\n","\n","- [Docs](https://python.langchain.com/v0.2/docs/how_to/vectorstores/): 如何使用向量数据库\n","- [Integrations](https://python.langchain.com/v0.2/docs/integrations/vectorstores/): 向量数据库继承，实现了`VectorStore` 接口的对象\n","- [Interface](https://api.python.langchain.com/en/latest/vectorstores/langchain_core.vectorstores.VectorStore.html): API调用\n","\n","这完成了链的索引部分。此时，我们拥有一个可查询的向量存储，其中包含博客文章内容的切分部分。针对用户提出的问题，理想情况下我们应该能够返回回答问题的博客文章内容。\n","\n","## 4. 检索和生成: 检索器\n","\n","现在让我们编写实际的应用逻辑。我们希望创建一个简单的应用，该应用接收用户提出的问题，搜索与该问题相关的文档，将检索到的文档和初始问题传递给一个模型，并返回一个答案。\n","\n","首先我们需要定义我们搜索文档的逻辑。LangChain定义了一个Retriever接口，它包装了一个索引，可以根据字符串查询返回相关的文档`Documents` 。\n","\n","向量存储转换为可执行的检索器，最常见的 `Retriever` 类型是[VectorStoreRetriever](https://python.langchain.com/v0.2/docs/how_to/vectorstore_retriever/)，它利用向量存储的相似度搜索功能来实现检索。任何 `VectorStore` 可以轻松地转换为 `Retriever` 使用`VectorStore.as_retriever()`。"]},{"cell_type":"code","execution_count":null,"id":"29009941","metadata":{"id":"29009941","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1717421690243,"user_tz":-480,"elapsed":1109,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"610418fd-f032-4d01-f910-7917292bd9ee"},"outputs":[{"output_type":"execute_result","data":{"text/plain":["6"]},"metadata":{},"execution_count":19}],"source":["retriever = vectorstore.as_retriever(search_type=\"similarity\", search_kwargs={\"k\": 6})\n","retrieved_docs = retriever.invoke(\"什么是Tree of Thoughts?\")\n","len(retrieved_docs)"]},{"cell_type":"code","execution_count":null,"id":"220b6a6e","metadata":{"id":"220b6a6e","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1717421692792,"user_tz":-480,"elapsed":1007,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"02c79958-e42d-47a4-b2e1-3046ca2d7264"},"outputs":[{"output_type":"stream","name":"stdout","text":["Tree of Thoughts (Yao et al. 2023) extends CoT by exploring multiple reasoning possibilities at each step. It first decomposes the problem into multiple thought steps and generates multiple thoughts per step, creating a tree structure. The search process can be BFS (breadth-first search) or DFS (depth-first search) with each state evaluated by a classifier (via a prompt) or majority vote.\n","Task decomposition can be done (1) by LLM with simple prompting like \"Steps for XYZ.\\n1.\", \"What are the subgoals for achieving XYZ?\", (2) by using task-specific instructions; e.g. \"Write a story outline.\" for writing a novel, or (3) with human inputs.\n"]}],"source":["print(retrieved_docs[0].page_content)"]},{"cell_type":"markdown","id":"a3dda385","metadata":{"id":"a3dda385"},"source":["### Go deeper\n","\n","对于检索器（retrieval）向量存储（Vector stores）是最常用的，但是也有其他检索器可以使用。\n","\n","`Retriever`: 一个传入查询的内容返回相关文本`Document` 列表的类\n","\n","- [Docs](https://python.langchain.com/v0.2/docs/how_to/#retrievers): 更多关于创建不同检索器的文档:\n","    - `MultiQueryRetriever` 生成[输入问题的变形](https://python.langchain.com/v0.2/docs/how_to/MultiQueryRetriever/)以提高检索命中率。\n","    - `MultiVectorRetriever` 生成[嵌入向量的变形](https://python.langchain.com/v0.2/docs/how_to/multi_vector/)，也是为了提高检索命中率。\n","    - `Max marginal relevance` 选择在检索的文档中相[关性和多样性](https://www.cs.cmu.edu/~jgc/publication/The_Use_MMR_Diversity_Based_LTMIR_1998.pdf)，以避免在重复的上下文中传递。\n","    - 在矢量存储检索期间，可以使用元数据过滤器对文档进行过滤，例如使用[Self Query retriver](https://python.langchain.com/v0.2/docs/how_to/self_query/)。\n","- [Integrations](https://python.langchain.com/v0.2/docs/integrations/retrievers/): 与检索服务的集成。\n","- [Interface](https://api.python.langchain.com/en/latest/retrievers/langchain_core.retrievers.BaseRetriever.html): API 调用。\n","\n","## 5. 检索和生成: 生成器\n","\n","让我们把所有内容整合成一个链条，以便接收问题，检索相关文档，构建提示，传递给模型，并解析输出。\n","\n","我们将使用gpt-3.5-turbo OpenAI聊天模型，但可以替换成任何LangChain LLM或ChatModel。"]},{"cell_type":"code","execution_count":null,"id":"7cf3daea","metadata":{"id":"7cf3daea"},"outputs":[],"source":["%%bash\n","pip install -qU langchain-openai"]},{"cell_type":"code","execution_count":null,"id":"53b75635","metadata":{"id":"53b75635"},"outputs":[],"source":["import getpass\n","import os\n","os.environ[\"OPENAI_API_KEY\"] = getpass.getpass()\n","from langchain_openai import ChatOpenAI\n","llm = ChatOpenAI(model=\"gpt-3.5-turbo-0125\")"]},{"cell_type":"markdown","id":"e82e3226","metadata":{"id":"e82e3226"},"source":["我们使用LangChain封装好的[RAG提示词](https://smith.langchain.com/hub/rlm/rag-prompt)模板。"]},{"cell_type":"code","execution_count":null,"id":"39b94745","metadata":{"id":"39b94745","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1717421898646,"user_tz":-480,"elapsed":5374,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"565654db-8eca-4bac-ee4f-0852a712298b"},"outputs":[{"output_type":"execute_result","data":{"text/plain":["[HumanMessage(content=\"You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know. Use three sentences maximum and keep the answer concise.\\nQuestion: filler question \\nContext: filler context \\nAnswer:\")]"]},"metadata":{},"execution_count":22}],"source":["from langchain import hub\n","prompt = hub.pull(\"rlm/rag-prompt\")\n","example_messages = prompt.invoke(\n","{\"context\": \"filler context\", \"question\": \"filler question\"}\n",").to_messages()\n","example_messages"]},{"cell_type":"code","execution_count":null,"id":"a1e69bc4","metadata":{"id":"a1e69bc4","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1717422002061,"user_tz":-480,"elapsed":561,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"7d990825-3c19-497b-df4d-25c6cbcee266"},"outputs":[{"output_type":"stream","name":"stdout","text":["You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know. Use three sentences maximum and keep the answer concise.\n","Question: filler question \n","Context: filler context \n","Answer:\n"]}],"source":["print(example_messages[0].content)"]},{"cell_type":"markdown","id":"b86e6114","metadata":{"id":"b86e6114"},"source":["我们使用LangChain的 [LCEL](https://python.langchain.com/v0.2/docs/concepts/#langchain-expression-language)  协议定义一个链\n","\n","这里是实现："]},{"cell_type":"code","execution_count":null,"id":"de21f46d","metadata":{"id":"de21f46d","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1717422085364,"user_tz":-480,"elapsed":12986,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"2b40e7a3-d3d8-4cb2-b35c-65adef0d5ac3"},"outputs":[{"output_type":"stream","name":"stdout","text":["Tree of Thoughts 是一个扩展了 CoT 的框架，由 Yao 等人于 2023 年提出。它通过在每个步骤探索多种推理可能性来拓展问题，首先将问题分解为多个思考步骤，并在每个步骤生成多个思考，从而创建了一棵树状结构。搜索过程可以是 BFS 或 DFS，每个状态都由分类器评估，通过提示或多数投票。"]}],"source":["from langchain_core.output_parsers import StrOutputParser\n","from langchain_core.runnables import RunnablePassthrough\n","def format_docs(docs):\n","  return \"\\n\\n\".join(doc.page_content for doc in docs)\n","rag_chain = (\n","{\"context\": retriever | format_docs, \"question\": RunnablePassthrough()}\n","| prompt\n","| llm\n","| StrOutputParser()\n",")\n","for chunk in rag_chain.stream(\"什么是Tree of Thoughts?\"):\n","  print(chunk, end=\"\", flush=True)"]},{"cell_type":"markdown","id":"a2df9a82","metadata":{"id":"a2df9a82"},"source":["**API 调用:**[StrOutputParser](https://api.python.langchain.com/en/latest/output_parsers/langchain_core.output_parsers.string.StrOutputParser.html) | [RunnablePassthrough](https://api.python.langchain.com/en/latest/runnables/langchain_core.runnables.passthrough.RunnablePassthrough.html)"]},{"cell_type":"markdown","id":"9ef172d7","metadata":{"id":"9ef172d7"},"source":["剖析理解什么是 LCEL\n","\n","首先：这些组件（`retriever`，`prompt`，`llm`等）都是`Runnable`的实例。这意味着它们实现了相同的方法，比如同步和异步的`.invoke`，`.stream`，或者`.batch`，这使它们更容易连接在一起。它们可以通过`|`操作符连接到[RunnabaleSequence](https://api.python.langchain.com/en/latest/runnables/langchain_core.runnables.base.RunnableSequence.html)（另一个`Runnable`）。\n","\n","在遇到`|`操作符时，LangChain会自动将某些对象转换为`Runnable`。在这里，`format_docs`被转换为[RunnableLambda](https://api.python.langchain.com/en/latest/runnables/langchain_core.runnables.base.RunnableLambda.html)，包含`context`和`question`的字典被转换为[RunnableParallel](https://api.python.langchain.com/en/latest/runnables/langchain_core.runnables.base.RunnableParallel.html)。只需要记住，那就是每个对象都是`Runnable`。\n","\n","让我们跟踪上面整个链，怎样输入问题到每一步的执行。\n","\n","正如我们在上面看到的，提示的输入应该是一个带有 `\"context\"`和`\"question\"`键的字典。因此，这个链的第一个元素将从输入的问题中拿到这两个值。\n","\n","- `retriever | format_docs` 通过检索器传递问题，生成文档对象，然后传递给 `format_docs` 生成字符串；\n","- `RunnablePassthrough()` 将输入的问题原封不动地传入进来\n","\n","That is, if you constructed"]},{"cell_type":"code","execution_count":null,"id":"a1eed7e5","metadata":{"id":"a1eed7e5"},"outputs":[],"source":["chain = (\n","{\"context\": retriever | format_docs, \"question\": RunnablePassthrough()}\n","| prompt\n",")"]},{"cell_type":"markdown","id":"3e42d27e","metadata":{"id":"3e42d27e"},"source":["那么，**`chain.invoke(question)`** 将构建一个格式化的提示词，准备进行推理。（注意：在使用 LCEL 开发时，一步一步拼装子链打印结果，非常有用）\n","\n","链的最后步骤是 **`llm`**，它进行推理，而 **`StrOutputParser()`** 则只是从 LLM 的输出消息中提取字符串内容。\n","\n","可以通过其 [LangSmith](https://smith.langchain.com/public/1799e8db-8a6d-4eb2-84d5-46e8d7d5a99b/r) 追踪来分析此链的各个步骤。\n","\n","### 内置链\n","\n","如果需要，LangChain 包含实现上述 LCEL 的便捷功能。我们组合了两个函数：\n","\n","- `create_stuff_documents_chain` 指定了如何检索上下文填充到提示词模板和 LLM中。在这种情况下，将把 `context` 内容全部“填充”到提示词中。这就实现了输入键为 `context` （上下文）和 `input` （输入问题）从提示词生成到大模型调用的过程。\n","- `create_retrieval_chain` 这个链中，相当于在上面定义的链前面加了个检索本地知识库的节点，将检索到的上下文交给上面定义好的链。它的输入键是 `input`，并在其输出中包含了 `input`、`context` 和 `answer`。"]},{"cell_type":"code","execution_count":null,"id":"6cd58565","metadata":{"id":"6cd58565","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1717422362353,"user_tz":-480,"elapsed":18717,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"4eea32d2-4bcf-414a-c92b-3a2bdf9b0e62"},"outputs":[{"output_type":"stream","name":"stdout","text":["Task decomposition is the process of breaking down a complex task into smaller and more manageable subtasks or steps. This approach enables agents or models to tackle intricate problems by addressing each component separately, facilitating clearer understanding and efficient problem-solving. Techniques like Chain of Thought (CoT) and Tree of Thoughts extend this concept by guiding models to think step by step or explore multiple reasoning possibilities at each step, respectively, enhancing their performance on complex tasks.Task decomposition is the process of breaking down a complex task into smaller and more manageable subtasks or steps. This approach enables agents or models to tackle intricate problems by addressing each component separately, facilitating clearer understanding and efficient problem-solving. Techniques like Chain of Thought (CoT) and Tree of Thoughts extend this concept by guiding models to think step by step or explore multiple reasoning possibilities at each step, respectively, enhancing their performance on complex tasks.\n"]}],"source":["from langchain.chains import create_retrieval_chain\n","from langchain.chains.combine_documents import create_stuff_documents_chain\n","from langchain_core.prompts import ChatPromptTemplate\n","system_prompt = (\n","\"You are an assistant for question-answering tasks. \"\n","\"Use the following pieces of retrieved context to answer \"\n","\"the question. If you don't know the answer, say that you \"\n","\"don't know. Use three sentences maximum and keep the \"\n","\"answer concise.\"\n","\"\\n\\n\"\n","\"{context}\"\n",")\n","prompt = ChatPromptTemplate.from_messages(\n","[\n","(\"system\", system_prompt),\n","(\"human\", \"{input}\"),\n","]\n",")\n","question_answer_chain = create_stuff_documents_chain(llm, prompt)\n","rag_chain = create_retrieval_chain(retriever, question_answer_chain)\n","response = rag_chain.invoke({\"input\": \"What is Task Decomposition?\"})\n","print(response[\"answer\"])\n"]},{"cell_type":"markdown","id":"de98bc41","metadata":{"id":"de98bc41"},"source":["**API 调用:**[create_retrieval_chain](https://api.python.langchain.com/en/latest/chains/langchain.chains.retrieval.create_retrieval_chain.html) | [create_stuff_documents_chain](https://api.python.langchain.com/en/latest/chains/langchain.chains.combine_documents.stuff.create_stuff_documents_chain.html) | [ChatPromptTemplate](https://api.python.langchain.com/en/latest/prompts/langchain_core.prompts.chat.ChatPromptTemplate.html)"]},{"cell_type":"markdown","id":"9848f31f","metadata":{"id":"9848f31f"},"source":["这种方法比上面 LCEL 链的优点是能够同时在**输出**中拿到`context` 和 `answer` ，而在 LCEL 链中我们只能拿到相关的输出，需要单独记录相应的上下文。\n","\n","### 返回来源\n","\n","在问答应用中，经常需要向用户展示用于生成答案的信息来源。LangChain 内置的 **`create_retrieval_chain`** 将检索到的源文档通过 `context` 键传递到输出中："]},{"cell_type":"code","execution_count":null,"id":"38723319","metadata":{"id":"38723319","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1717422446831,"user_tz":-480,"elapsed":658,"user":{"displayName":"李辉","userId":"12972001611808140221"}},"outputId":"59aace0b-daf2-4ebf-e51a-66e2efc80cae"},"outputs":[{"output_type":"stream","name":"stdout","text":["page_content='Fig. 1. Overview of a LLM-powered autonomous agent system.\\nComponent One: Planning#\\nA complicated task usually involves many steps. An agent needs to know what they are and plan ahead.\\nTask Decomposition#\\nChain of thought (CoT; Wei et al. 2022) has become a standard prompting technique for enhancing model performance on complex tasks. The model is instructed to “think step by step” to utilize more test-time computation to decompose hard tasks into smaller and simpler steps. CoT transforms big tasks into multiple manageable tasks and shed lights into an interpretation of the model’s thinking process.' metadata={'source': 'https://lilianweng.github.io/posts/2023-06-23-agent/', 'start_index': 1585}\n","page_content='Tree of Thoughts (Yao et al. 2023) extends CoT by exploring multiple reasoning possibilities at each step. It first decomposes the problem into multiple thought steps and generates multiple thoughts per step, creating a tree structure. The search process can be BFS (breadth-first search) or DFS (depth-first search) with each state evaluated by a classifier (via a prompt) or majority vote.\\nTask decomposition can be done (1) by LLM with simple prompting like \"Steps for XYZ.\\\\n1.\", \"What are the subgoals for achieving XYZ?\", (2) by using task-specific instructions; e.g. \"Write a story outline.\" for writing a novel, or (3) with human inputs.' metadata={'source': 'https://lilianweng.github.io/posts/2023-06-23-agent/', 'start_index': 2192}\n","page_content='Resources:\\n1. Internet access for searches and information gathering.\\n2. Long Term memory management.\\n3. GPT-3.5 powered Agents for delegation of simple tasks.\\n4. File output.\\n\\nPerformance Evaluation:\\n1. Continuously review and analyze your actions to ensure you are performing to the best of your abilities.\\n2. Constructively self-criticize your big-picture behavior constantly.\\n3. Reflect on past decisions and strategies to refine your approach.\\n4. Every command has a cost, so be smart and efficient. Aim to complete tasks in the least number of steps.' metadata={'source': 'https://lilianweng.github.io/posts/2023-06-23-agent/', 'start_index': 29630}\n","page_content=\"(3) Task execution: Expert models execute on the specific tasks and log results.\\nInstruction:\\n\\nWith the input and the inference results, the AI assistant needs to describe the process and results. The previous stages can be formed as - User Input: {{ User Input }}, Task Planning: {{ Tasks }}, Model Selection: {{ Model Assignment }}, Task Execution: {{ Predictions }}. You must first answer the user's request in a straightforward manner. Then describe the task process and show your analysis and model inference results to the user in the first person. If inference results contain a file path, must tell the user the complete file path.\" metadata={'source': 'https://lilianweng.github.io/posts/2023-06-23-agent/', 'start_index': 19373}\n","page_content='The AI assistant can parse user input to several tasks: [{\"task\": task, \"id\", task_id, \"dep\": dependency_task_ids, \"args\": {\"text\": text, \"image\": URL, \"audio\": URL, \"video\": URL}}]. The \"dep\" field denotes the id of the previous task which generates a new resource that the current task relies on. A special tag \"-task_id\" refers to the generated text image, audio and video in the dependency task with id as task_id. The task MUST be selected from the following options: {{ Available Task List }}. There is a logical relationship between tasks, please note their order. If the user input can\\'t be parsed, you need to reply empty JSON. Here are several cases for your reference: {{ Demonstrations }}. The chat history is recorded as {{ Chat History }}. From this chat history, you can find the path of the user-mentioned resources for your task planning.' metadata={'source': 'https://lilianweng.github.io/posts/2023-06-23-agent/', 'start_index': 17804}\n","page_content='Fig. 11. Illustration of how HuggingGPT works. (Image source: Shen et al. 2023)\\nThe system comprises of 4 stages:\\n(1) Task planning: LLM works as the brain and parses the user requests into multiple tasks. There are four attributes associated with each task: task type, ID, dependencies, and arguments. They use few-shot examples to guide LLM to do task parsing and planning.\\nInstruction:' metadata={'source': 'https://lilianweng.github.io/posts/2023-06-23-agent/', 'start_index': 17414}\n","\n"]}],"source":["for document in response[\"context\"]:\n","  print(document)\n","print()"]},{"cell_type":"markdown","id":"d16cd734","metadata":{"id":"d16cd734"},"source":["### Go deeper\n","\n","### 模型选择\n","\n","`ChatModel`: 一个 LLM 支持的聊天模型。接收一系列消息并返回一条消息。\n","\n","- [Docs](https://python.langchain.com/v0.2/docs/how_to/#chat-models)\n","- [Integrations](https://python.langchain.com/v0.2/docs/integrations/chat/): 25+ 可供选择的集成。\n","- [Interface](https://api.python.langchain.com/en/latest/language_models/langchain_core.language_models.chat_models.BaseChatModel.html): API 调用。\n","\n","`LLM`: 一个 text-in-text-out LLM。接受一个字符串并返回一个字符串。\n","\n","- [Docs](https://python.langchain.com/v0.2/docs/how_to/#llms)\n","- [Integrations](https://python.langchain.com/v0.2/docs/integrations/llms/): 75+  可供选择的集成。\n","- [Interface](https://api.python.langchain.com/en/latest/language_models/langchain_core.language_models.llms.BaseLLM.html): API 调用。\n","\n","### 自定义模板\n","\n","如上所示，我们可以从直接加载预先设定的提示词(例如，这个 [RAG 提示](https://smith.langchain.com/hub/rlm/rag-prompt)词)。自定义提示词也很容易："]},{"cell_type":"code","execution_count":null,"id":"5d5ab30b","metadata":{"id":"5d5ab30b"},"outputs":[],"source":["from langchain_core.prompts import PromptTemplate\n","template = \"\"\"Use the following pieces of context to answer the question at the end.\n","If you don't know the answer, just say that you don't know, don't try to make up an answer.\n","Use three sentences maximum and keep the answer as concise as possible.\n","Always say \"thanks for asking!\" at the end of the answer.\n","{context}\n","Question: {question}\n","Helpful Answer:\"\"\"\n","custom_rag_prompt = PromptTemplate.from_template(template)\n","rag_chain = (\n","{\"context\": retriever | format_docs, \"question\": RunnablePassthrough()}\n","| custom_rag_prompt\n","| llm\n","| StrOutputParser()\n",")\n","rag_chain.invoke(\"What is Task Decomposition?\")"]},{"cell_type":"markdown","id":"efde1266","metadata":{"id":"efde1266"},"source":["**API 调用:**[PromptTemplate](https://api.python.langchain.com/en/latest/prompts/langchain_core.prompts.prompt.PromptTemplate.html)"]},{"cell_type":"markdown","id":"9c400129","metadata":{"id":"9c400129"},"source":["[LangSmith trace](https://smith.langchain.com/public/da23c4d8-3b33-47fd-84df-a3a582eedf84/r)\n","\n","## 总结\n","\n","我们已经介绍了构建基本问答应用程序的所有步骤：\n","\n","- 使用[文档加载器](https://python.langchain.com/v0.2/docs/concepts/#document-loaders)加载数据\n","- 使用[文本拆分器](https://python.langchain.com/v0.2/docs/concepts/#text-splitters)对索引数据进行分块，以便模型更容易使用\n","- 对数据进行[嵌入](https://python.langchain.com/v0.2/docs/concepts/#embedding-models)，并将数据存储在[向量存储器](https://python.langchain.com/v0.2/docs/how_to/vectorstores/)中\n","- 根据传入的问题[检索](https://python.langchain.com/v0.2/docs/concepts/#retrievers)先前存储的分块\n","- 使用检索到的分块作为上下文生成答案"]}],"metadata":{"colab":{"provenance":[]},"language_info":{"name":"python"},"kernelspec":{"name":"python3","display_name":"Python 3"}},"nbformat":4,"nbformat_minor":5}